package com.wgj.android.ui.activity;

import android.Manifest;
import android.annotation.TargetApi;
import android.app.Activity;
import android.app.Dialog;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.graphics.Color;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.text.TextUtils;
import android.view.View;
import android.view.Window;

import com.baidu.location.BDAbstractLocationListener;
import com.baidu.location.BDLocation;
import com.baidu.location.LocationClient;
import com.baidu.location.LocationClientOption;
import com.baidu.mapapi.map.BaiduMap;
import com.baidu.mapapi.map.BitmapDescriptor;
import com.baidu.mapapi.map.BitmapDescriptorFactory;
import com.baidu.mapapi.map.MapStatus;
import com.baidu.mapapi.map.MapStatusUpdate;
import com.baidu.mapapi.map.MapStatusUpdateFactory;
import com.baidu.mapapi.map.MapView;
import com.baidu.mapapi.map.Marker;
import com.baidu.mapapi.map.MarkerOptions;
import com.baidu.mapapi.map.OverlayOptions;
import com.baidu.mapapi.map.UiSettings;
import com.baidu.mapapi.model.LatLng;
import com.baidu.mapapi.search.core.PoiInfo;
import com.baidu.mapapi.search.geocode.GeoCodeResult;
import com.baidu.mapapi.search.geocode.GeoCoder;
import com.baidu.mapapi.search.geocode.OnGetGeoCoderResultListener;
import com.baidu.mapapi.search.geocode.ReverseGeoCodeOption;
import com.baidu.mapapi.search.geocode.ReverseGeoCodeResult;
import com.baidu.mapapi.search.poi.OnGetPoiSearchResultListener;
import com.baidu.mapapi.search.poi.PoiDetailResult;
import com.baidu.mapapi.search.poi.PoiIndoorResult;
import com.baidu.mapapi.search.poi.PoiNearbySearchOption;
import com.baidu.mapapi.search.poi.PoiResult;
import com.baidu.mapapi.search.poi.PoiSearch;
import com.baidu.mapapi.search.poi.PoiSortType;
import com.baidu.mapapi.utils.DistanceUtil;
import com.jiaai.xui.adapter.decoration.DividerDecoration;
import com.jiaai.xui.utils.XDensityUtils;
import com.jiaai.xui.view.widget.XTopbarView;
import com.wgj.android.R;
import com.wgj.android.adapter.MapAdapter;
import com.wgj.android.dialog.BaiDuSearchDialog;
import com.wgj.android.entity.Address;
import com.wgj.android.events.LocationEvent;
import com.wgj.android.fragment.CardFragment;
import com.wgj.android.utils.Utils;

import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;
import org.greenrobot.eventbus.ThreadMode;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;

import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;

public class MapActivity extends AppCompatActivity implements OnGetPoiSearchResultListener,XTopbarView.OnTopBarClickListener{
    private final int SDK_PERMISSION_REQUEST = 127;
    public static final int MAP_REQUESTCODE = 1450;
    public static final int MAP_RESULTCODE = 1450;
    @BindView(R.id.list)
    RecyclerView listView;
    @BindView(R.id.topBar)
    XTopbarView topBar;
    private MapAdapter adapter;
    public LocationClient mLocationClient;
    private BaiduMap mBaiduMap;
    private MapView map;
    private LinkedList<LocationEntity> locationList = new LinkedList<LocationEntity>(); // 存放历史定位结果的链表，最大存放当前结果的前5次定位结果
    private double lat;
    private double lon;
    private List<PoiInfo> poiList = new ArrayList<>();
    private Marker marker;
    private LocationClientOption option;
    private UiSettings mUiSettings;
    private PoiSearch mPoiSearch = null;

    private String cityName;
    private Location location;
    private BaiDuSearchDialog dialog;
    public static void toMapActivity(Activity activity) {
        Intent intent = new Intent(activity, MapActivity.class);
        activity.startActivityForResult(intent, MAP_REQUESTCODE);
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_map);
        ButterKnife.bind(this);
        getPersimmions();
        initView();
        initMap();
    }

    private void initView() {

        topBar.setTopBarClickListener(this);
        LinearLayoutManager layoutManager = new LinearLayoutManager(this);
        layoutManager.setOrientation(LinearLayoutManager.VERTICAL);
        listView.setLayoutManager(layoutManager);
        listView.addItemDecoration(new DividerDecoration(Color.BLACK, XDensityUtils.dp2px(1f)));
        adapter = new MapAdapter(MapActivity.this, poiList);
        listView.setAdapter(adapter);
        adapter.setOnItemClickListener(new MapAdapter.OnItemClickListener() {
            @Override
            public void onItemClick(View view, int position) {
                //view.findViewById(R.id.image).setVisibility(View.VISIBLE);
                location = new Location();
                location.setAddress(poiList.get(position).address);
                location.setLatitude(poiList.get(position).location.latitude);
                location.setLongitude(poiList.get(position).location.longitude);
                Intent intent = new Intent();
                Bundle bundle = new Bundle();
                bundle.putSerializable("location", location);
                intent.putExtras(bundle);
                setResult(MAP_RESULTCODE, intent);
                finish();
            }
        });
    }

    private void initMap() {
        map = findViewById(R.id.map);
        mBaiduMap = map.getMap();
        mUiSettings = mBaiduMap.getUiSettings();
        mUiSettings.setAllGesturesEnabled(true);
        mUiSettings.setCompassEnabled(true);
        mUiSettings.setZoomGesturesEnabled(true);
        mUiSettings.setOverlookingGesturesEnabled(true);
        mUiSettings.setRotateGesturesEnabled(true);
        mUiSettings.setScrollGesturesEnabled(true);
        mBaiduMap.showMapPoi(true);
        mBaiduMap.setMapType(BaiduMap.MAP_TYPE_NORMAL);
        // 开启定位图层
        mBaiduMap.setMyLocationEnabled(true);
        // 设置启用内置的缩放控件
        mBaiduMap.setMapStatus(MapStatusUpdateFactory.zoomTo(15));
        option = new LocationClientOption();
        option.setScanSpan(500);
        option.setLocationMode(LocationClientOption.LocationMode.Battery_Saving);
        option.setIsNeedAddress(true);
        option.setCoorType("bd09ll");
        //option.setL
        option.setIsNeedLocationPoiList(true);
        if (mLocationClient == null) {
            //声明LocationClient类
            mLocationClient = new LocationClient(getApplicationContext());

        }
        mLocationClient.setLocOption(option);
        //注册监听函数
        mLocationClient.registerLocationListener(listener);
        mLocationClient.start();

        //地图状态改变相关接口
        mBaiduMap.setOnMapStatusChangeListener(new BaiduMap.OnMapStatusChangeListener() {

            @Override
            public void onMapStatusChangeStart(MapStatus arg0) {
                // 手势操作地图，设置地图状态等操作导致地图状态开始改变。
            }

            @Override
            public void onMapStatusChangeStart(MapStatus mapStatus, int i) {
            }

            @Override
            public void onMapStatusChange(MapStatus mapStatus) {
                if (marker != null) {
                    marker.setPosition(mapStatus.target);
                }
            }

            @Override
            public void onMapStatusChangeFinish(MapStatus mapStatus) {
                GeoCoder geocoder = GeoCoder.newInstance();
                geocoder.reverseGeoCode(new ReverseGeoCodeOption().location(mapStatus.target));
                geocoder.setOnGetGeoCodeResultListener(new OnGetGeoCoderResultListener() {
                    @Override
                    public void onGetGeoCodeResult(GeoCodeResult geoCodeResult) {
                    }

                    @Override
                    public void onGetReverseGeoCodeResult(ReverseGeoCodeResult reverseGeoCodeResult) {
                        String address = reverseGeoCodeResult.getAddress();
                        if (!TextUtils.isEmpty(address)) {
                            reverseGeoCodeResult.getLocation();
                        }
                    }
                });

                LatLng target = mapStatus.target;
                PoiNearbySearchOption nearbySearchOption = new PoiNearbySearchOption().keyword("生活服务").sortType(PoiSortType.distance_from_near_to_far).location(target)
                        .radius(1000).pageNum(10);
                mPoiSearch.searchNearby(nearbySearchOption);
                mBaiduMap.setMyLocationEnabled(false);
                if (mLocationClient.isStarted()) {
                    mLocationClient.stop();
                }
            }
        });
        // 初始化搜索模块，注册搜索事件监听
        mPoiSearch = PoiSearch.newInstance();
        mPoiSearch.setOnGetPoiSearchResultListener(this);
    }

    private BDAbstractLocationListener listener = new BDAbstractLocationListener() {
        @Override
        public void onReceiveLocation(BDLocation location) {
            // TODO Auto-generated method stub
            if (null != location && location.getLocType() != BDLocation.TypeServerError) {
                Message locMsg = locHander.obtainMessage();
                Bundle locData;
                locData = Algorithm(location);
                if (locData != null) {
                    mBaiduMap.clear();//移除图标
                    locData.putParcelable("loc", location);
                    locMsg.setData(locData);
                    locHander.sendMessage(locMsg);
                }
                // 国家名称
                String str = location.getCountry();
                // 城市
                cityName = location.getCity();
                // 城市编码
                String str2 = location.getCityCode();
                LocationEvent event = new LocationEvent();
                event.setName(cityName);
                EventBus.getDefault().postSticky(event);
            }
            lat = location.getLatitude();
            lon = location.getLongitude();
            setUserMapCenter();

            LatLng latLng = new LatLng(lat, lon);
            PoiNearbySearchOption nearbySearchOption = new PoiNearbySearchOption().keyword("生活服务").sortType(PoiSortType.distance_from_near_to_far).location(latLng)
                    .radius(1000).pageNum(10);
            mPoiSearch.searchNearby(nearbySearchOption);
        }
    };

    private void setUserMapCenter() {
        LatLng cenpt = new LatLng(lat, lon);
        //定义地图状态
        MapStatus mMapStatus = new MapStatus.Builder()
                .target(cenpt)
                .zoom(18)
                .build();
        //定义MapStatusUpdate对象，以便描述地图状态将要发生的变化
        MapStatusUpdate mMapStatusUpdate = MapStatusUpdateFactory.newMapStatus(mMapStatus);
        //改变地图状态
        mBaiduMap.setMapStatus(mMapStatusUpdate);
    }

    /**
     * 平滑策略代码实现方法，主要通过对新定位和历史定位结果进行速度评分，
     * 来判断新定位结果的抖动幅度，如果超过经验值，则判定为过大抖动，进行平滑处理,若速度过快，
     * 则推测有可能是由于运动速度本身造成的，则不进行低速平滑处理 ╭(●｀∀´●)╯
     *
     * @param location
     * @return Bundle
     */
    private Bundle Algorithm(BDLocation location) {
        Bundle locData = new Bundle();
        double curSpeed = 0;
        if (locationList.isEmpty() || locationList.size() < 2) {
            LocationEntity temp = new LocationEntity();
            temp.location = location;
            temp.time = System.currentTimeMillis();
            locData.putInt("iscalculate", 0);
            locationList.add(temp);
        } else {
            if (locationList.size() > 5)
                locationList.removeFirst();
            double score = 0;
            for (int i = 0; i < locationList.size(); ++i) {
                LatLng lastPoint = new LatLng(locationList.get(i).location.getLatitude(),
                        locationList.get(i).location.getLongitude());
                LatLng curPoint = new LatLng(location.getLatitude(), location.getLongitude());
                double distance = DistanceUtil.getDistance(lastPoint, curPoint);
                curSpeed = distance / (System.currentTimeMillis() - locationList.get(i).time) / 1000;
                score += curSpeed * Utils.EARTH_WEIGHT[i];
            }
            if (score > 0.00000999 && score < 0.00005) { // 经验值,开发者可根据业务自行调整，也可以不使用这种算法
                location.setLongitude(
                        (locationList.get(locationList.size() - 1).location.getLongitude() + location.getLongitude())
                                / 2);
                location.setLatitude(
                        (locationList.get(locationList.size() - 1).location.getLatitude() + location.getLatitude())
                                / 2);
                locData.putInt("iscalculate", 1);
            } else {
                locData.putInt("iscalculate", 0);
            }
            LocationEntity newLocation = new LocationEntity();
            newLocation.location = location;
            newLocation.time = System.currentTimeMillis();
            locationList.add(newLocation);

        }
        return locData;
    }

    /**
     * 接收定位结果消息，并显示在地图上
     */

    private Handler locHander = new Handler() {

        @Override
        public void handleMessage(Message msg) {
            // TODO Auto-generated method stub
            super.handleMessage(msg);
            try {
                BDLocation location = msg.getData().getParcelable("loc");
                int iscal = msg.getData().getInt("iscalculate");
                if (location != null) {
                    LatLng point = new LatLng(location.getLatitude(), location.getLongitude());
                    // 构建Marker图标
                    BitmapDescriptor bitmap = null;
                    if (iscal == 0) {
                        bitmap = BitmapDescriptorFactory.fromResource(R.drawable.icon_openmap_mark); // 非推算结果
                    } else {
                        bitmap = BitmapDescriptorFactory.fromResource(R.drawable.icon_openmap_focuse_mark); // 推算结果
                    }

                    // 构建MarkerOption，用于在地图上添加Marker
                    OverlayOptions option = new MarkerOptions().position(point).icon(bitmap);
                    // 在地图上添加Marker，并显示
                    marker = (Marker) mBaiduMap.addOverlay(option);
                    mBaiduMap.setMapStatus(MapStatusUpdateFactory.newLatLng(point));
                }
            } catch (Exception e) {
                // TODO: handle exception
            }
        }
    };

    @Override
    protected void onDestroy() {

        mLocationClient.unRegisterLocationListener(listener); //注销掉监听
        mLocationClient.stop();
        map.onDestroy();//停止定位服务
        super.onDestroy();
    }

    @Override
    protected void onPause() {
        super.onPause();
        //在activity执行onPause时执行mMapView. onPause ()，实现地图生命周期管理
        map.onPause();
    }

    @Override
    protected void onResume() {
        super.onResume();
        //在activity执行onResume时执行mMapView. onResume ()，实现地图生命周期管理
        map.onResume();
    }

    @Override
    public void onGetPoiResult(PoiResult poiResult) {
        if (poiResult.getAllPoi() != null && poiResult.getAllPoi().size() != 0) {
            poiList.clear();
            poiList.addAll(poiResult.getAllPoi());
            adapter.notifyDataSetChanged();
        }
    }

    @Override
    public void onGetPoiDetailResult(PoiDetailResult poiDetailResult) {
        String list = poiDetailResult.getAddress();
    }

    @Override
    public void onGetPoiIndoorResult(PoiIndoorResult poiIndoorResult) {

    }

    @Override
    public void onBackClick() {
        finish();
    }

    @Override
    public void onRightButClick() {
        dialog = new BaiDuSearchDialog();
        dialog.setAddCallback(new BaiDuSearchDialog.OnSelectAddCallback() {
            @Override
            public void onSelect(Address address) {
               /* PoiNearbySearchOption nearbySearchOption = new PoiNearbySearchOption().keyword("生活服务").sortType(PoiSortType.distance_from_near_to_far).location(address)
                        .radius(1000).pageNum(10);
                mPoiSearch.searchNearby(nearbySearchOption);*/
                PoiInfo poiInfo =new PoiInfo();
                poiInfo.location=address.getLatLng();
                poiInfo.name=address.getName();
                poiInfo.address=address.getAddress();
                poiList.add(0,poiInfo);
                adapter.notifyDataSetChanged();
            }
        });
        dialog.show(getSupportFragmentManager(),"");

    }

    /*
         * 封装定位结果和时间的实体类
         *
         * @author baidu
    */
    class LocationEntity {
        BDLocation location;
        long time;
    }

    @OnClick(R.id.image)
    public void onClick(View v) {
        //mBaiduMap.clear();
        mBaiduMap.setMyLocationEnabled(true);
        mLocationClient.start();
    }

    static class Location implements Serializable {
        private double latitude;
        private double longitude;
        private String address;

        public double getLatitude() {
            return latitude;
        }

        public void setLatitude(double latitude) {
            this.latitude = latitude;
        }

        public double getLongitude() {
            return longitude;
        }

        public void setLongitude(double longitude) {
            this.longitude = longitude;
        }

        public String getAddress() {
            return address;
        }

        public void setAddress(String address) {
            this.address = address;
        }
    }

    @TargetApi(23)
    private void getPersimmions() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            ArrayList<String> permissions = new ArrayList<String>();
            /***
             * 定位权限为必须权限，用户如果禁止，则每次进入都会申请
             */
            // 定位精确位置
            if (checkSelfPermission(Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
                permissions.add(Manifest.permission.ACCESS_FINE_LOCATION);
            }
            if (checkSelfPermission(Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
                permissions.add(Manifest.permission.ACCESS_COARSE_LOCATION);
            }

            if (permissions.size() > 0) {
                requestPermissions(permissions.toArray(new String[permissions.size()]), SDK_PERMISSION_REQUEST);
            }
        }
    }

    @TargetApi(23)
    @Override
    public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
        // TODO Auto-generated method stub
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);

    }
}
